package com.example.android.story.Utils;

import android.app.Application;
import android.arch.lifecycle.LiveData;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

import java.io.File;
import java.util.List;

import cn.bmob.v3.BmobObject;
import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.datatype.BmobFile;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.DownloadFileListener;
import cn.bmob.v3.listener.FindListener;
import cn.bmob.v3.listener.SaveListener;
import cn.bmob.v3.listener.UpdateListener;
import cn.bmob.v3.listener.UploadFileListener;

/**
 * Created by liwei on 2018/5/22.
 */

public class StoryRepository {
    private Context ctx;
    private LocalDatabase db;
    private UserDao userDao;
    private StoryDao storyDao;
    private ActorDao actorDao;
    private RememberMeDao rememberMeDao;
    private LiveData<List<User>> allUsers;
    private LiveData<List<Story>> allStories;
    private LiveData<List<Actor>> allActors;

    public StoryRepository(Application application){
        ctx=application;
        db=LocalDatabase.getDatabase(application);
        userDao=db.userDao();
        allUsers=userDao.getAllUsersLiveData();
        storyDao=db.storyDao();
        allStories=storyDao.getAllStoriesLiveData();
        actorDao=db.actorDao();
        allActors=actorDao.getAllActorsLiveData();
        rememberMeDao=db.rememberMeDao();
        new syncDataTask(ctx,userDao,storyDao,actorDao).execute();

    }

    public LiveData<List<User>> getAllUsers(){
        return allUsers;
    }

    public LiveData<List<ActorsInStory>> getActorsInStory(String storyTitle){
        return db.actorsInStoryDao().getAllActorsInStoryLiveData(storyTitle);
    }

    public LiveData<List<Story>> getAllStories() {
        return allStories;
    }

    public LiveData<List<Actor>> getAllActors(){return allActors;}

    public LiveData<List<Purchased>> getPurchased(String username){
        return db.purchasedDao().getPurchasedLiveData(username);
    }

    public LiveData<User> getRememberMe(){
        return db.rememberMeDao().getRememberMe();
    }
    public void eraseRememberMe(){
        new eraseRememberMeAsyncTask(rememberMeDao).execute();
    }

    public void insert(User user){
        new insertUserAsyncTask(userDao,true).execute(user);
    }
    public void insert(Actor actor){
        new insertActorAsyncTask(actorDao,true).execute(actor);
    }
    public void insert(Story story){
        new insertStoryAsyncTask(storyDao,true).execute(story);
    }
    public void insert(ActorsInStory actorsInStory){
        new insertActorInStoryAsyncTask(db.actorsInStoryDao()).execute(actorsInStory);
    }
    public void insert(Purchased purchased){
        new insertPurchasedAsyncTask(db.purchasedDao()).execute(purchased);
    }
    public void insert(RememberMe rememberMe){
        new insertRememberMeAsyncTask(rememberMeDao).execute(rememberMe);
    }

    private static class insertUserAsyncTask extends AsyncTask<User,Void,Void>{

        private UserDao asyncUserDao;
        private boolean insertOnline=true;

        public insertUserAsyncTask(UserDao userDao,boolean insertOnline){
            this.asyncUserDao=userDao;
            this.insertOnline=insertOnline;
        }
        @Override
        protected Void doInBackground(User... users) {
            try{
                this.asyncUserDao.insertUser(users[0]);
                if(insertOnline){
                    User user=users[0];
                    user.getBmobObject().save(new SaveListener<String>() {
                        @Override
                        public void done(String objId, BmobException e) {
                            if(e==null)
                                Log.d("debug","upload user successful : "+objId);
                            else
                                Log.d("debug", "bomb upload failed");;
                        }
                    });
                }
            }catch (Exception e){
                Log.d("debug",e.getMessage());
            }
            return null;
        }
    }
    private static class insertStoryAsyncTask extends AsyncTask<Story,Void,Void>{
        private StoryDao asyncStoryDao;
        private boolean insertOnline;
        insertStoryAsyncTask(StoryDao asyncStoryDao,boolean insertOnline){
            this.asyncStoryDao=asyncStoryDao;
            this.insertOnline=insertOnline;
        }
        @Override
        protected Void doInBackground(Story... stories) {
            try{
                this.asyncStoryDao.insertStory(stories[0]);
                if(insertOnline){

                    final Story.StoryObj obj= (Story.StoryObj) stories[0].getBmobObject();
                    obj.save(new SaveListener<String>() {
                        @Override
                        public void done(String objId, BmobException e) {
                            if(e==null)
                                Log.d("debug","upload story successful : "+objId);
                            else
                                Log.d("debug", "bomb upload failed");;
                        }
                    });
                    final BmobFile picFile=new BmobFile(new File(stories[0].getPicture()));
                    picFile.uploadblock(new UploadFileListener() {
                        @Override
                        public void done(BmobException e) {
                            obj.setPicture(picFile.getFileUrl());
                            obj.update(new UpdateListener() {
                                @Override
                                public void done(BmobException e) {

                                }
                            });
                        }
                    });
                    final BmobFile musicFile=new BmobFile(new File(stories[0].getMusic()));
                    musicFile.uploadblock(new UploadFileListener() {
                        @Override
                        public void done(BmobException e) {
                            obj.setMusic(musicFile.getFileUrl());
                            obj.update(new UpdateListener() {
                                @Override
                                public void done(BmobException e) {

                                }
                            });
                        }
                    });
                }
            }catch (Exception e){
                Log.d("debug",e.getMessage());
            }
            return null;
        }

    }
    private static class insertActorAsyncTask extends AsyncTask<Actor,Void,Void>{
        private ActorDao asyncActorDao;
        private boolean insertOnline;
        insertActorAsyncTask(ActorDao actorDao,boolean insertOnline){
            this.asyncActorDao=actorDao;
            this.insertOnline=insertOnline;
        }

        @Override
        protected Void doInBackground(Actor... actors) {
            try{
                this.asyncActorDao.insert(actors[0]);
                if(!insertOnline)
                    return null;
                final Actor.ActorObj obj= (Actor.ActorObj) actors[0].getBmobObject();
                obj.save();

                final BmobFile bundleFile=new BmobFile(new File(obj.getBundle()));
                bundleFile.uploadblock(new UploadFileListener() {
                    @Override
                    public void done(BmobException e) {
                        obj.setBundle(bundleFile.getFileUrl());
                        obj.update(new UpdateListener() {
                            @Override
                            public void done(BmobException e) {

                            }
                        });
                    }
                });

                final BmobFile pictureFile=new BmobFile(new File(obj.getPicture()));
                pictureFile.uploadblock(new UploadFileListener() {
                    @Override
                    public void done(BmobException e) {
                        obj.setPicture(pictureFile.getFileUrl());
                        obj.update(new UpdateListener() {
                            @Override
                            public void done(BmobException e) {

                            }
                        });
                    }
                });
            }catch(Exception e){
                Log.d("debug",e.getMessage());
            }
            return null;
        }
    }

    private static class insertActorInStoryAsyncTask extends AsyncTask<ActorsInStory,Void,Void>{
        private ActorsInStoryDao asyncActorsInStoryDao;
        insertActorInStoryAsyncTask(ActorsInStoryDao actorsInStoryDao){this.asyncActorsInStoryDao=actorsInStoryDao;}

        @Override
        protected Void doInBackground(ActorsInStory... actorsInStories) {
            try{
                this.asyncActorsInStoryDao.insertActorsInStory(actorsInStories[0]);
                actorsInStories[0].getBmobObject().save();
            }catch(Exception e){
                Log.d("debug",e.getMessage());
            }
            return null;
        }
    }

    private static class insertPurchasedAsyncTask extends AsyncTask<Purchased,Void,Void>{
        private PurchasedDao asyncPurchasedDao;
        insertPurchasedAsyncTask(PurchasedDao purchasedDao){this.asyncPurchasedDao=purchasedDao;}

        @Override
        protected Void doInBackground(Purchased... purchaseds) {
            try{
                asyncPurchasedDao.insert(purchaseds[0]);
                purchaseds[0].getBmobObject().save();
            }catch (Exception e){
                Log.d("debug",e.getMessage());
            }
            return null;
        }
    }
    private static class insertRememberMeAsyncTask extends AsyncTask<RememberMe,Void,Void>{
        private RememberMeDao asyncRememberMeDao;
        insertRememberMeAsyncTask(RememberMeDao rememberMeDao){this.asyncRememberMeDao=rememberMeDao;}

        @Override
        protected Void doInBackground(RememberMe... rememberMes) {
            try{
                asyncRememberMeDao.insert(rememberMes[0]);
            }catch (Exception e){

            }
            return null;
        }
    }
    private  static class eraseRememberMeAsyncTask extends AsyncTask<Void,Void,Void>{
        private RememberMeDao asyncRememberMeDao;
        eraseRememberMeAsyncTask(RememberMeDao asyncRememberMeDao){
            this.asyncRememberMeDao=asyncRememberMeDao;
        }
        @Override
        protected Void doInBackground(Void... voids) {
            asyncRememberMeDao.erase();
            return null;
        }
    }
    private static class syncDataTask extends AsyncTask<Void,Void,Void>{
        private Context ctx;
        private UserDao asyncUserDao;
        private StoryDao asyncStoryDao;
        private ActorDao asyncActorDao;
        public syncDataTask(
                Context ctx
                ,UserDao asyncUserDao
                ,StoryDao asyncStoryDao
                ,ActorDao asyncActorDao
        ){
            this.ctx=ctx;
            this.asyncUserDao=asyncUserDao;
            this.asyncStoryDao=asyncStoryDao;
            this.asyncActorDao=asyncActorDao;
        }
        @Override
        protected Void doInBackground(Void... voids) {
            BmobQuery<User.UserObj> queryUser = new BmobQuery<User.UserObj>();
            //返回50条数据，如果不加上这条语句，默认返回10条数据，最多500
//        query.setLimit(500);
            //执行查询方法
            queryUser.findObjects(new FindListener<User.UserObj>() {

                @Override
                public void done(List<User.UserObj> list, BmobException e) {
                    if(e==null){
                        for(User.UserObj obj: list){
                            User user=new User();
                            user.setCoins(obj.getCoins());
                            user.setName(obj.getName());
                            user.setPassword(obj.getPassword());
                            user.setSalt(obj.getSalt());
                            new insertUserAsyncTask(asyncUserDao,false).execute(user);
                        }
                    }else{
                    }
                }
            });

            BmobQuery<Story.StoryObj> queryStory=new BmobQuery<>();
            queryStory.findObjects(new FindListener<Story.StoryObj>() {
                @Override
                public void done(List<Story.StoryObj> list, BmobException e) {
                    if(e==null){
                        for(Story.StoryObj obj:list){
                            Story story=new Story();
                            story.setPrice(obj.getPrice());
                            story.setPicture(ctx.getFilesDir()+"/"+obj.getTitle()+".jpg");
                            story.setMusic(ctx.getFilesDir()+"/"+obj.getTitle()+".mp3");
                            story.setBundle(obj.getBundle());
                            story.setTitle(obj.getTitle());
                            new insertStoryAsyncTask(asyncStoryDao,false).execute(story);
                            downloadFile(story.getPicture(),obj.getPicture());
                            downloadFile(story.getMusic(),obj.getMusic());
                        }
                    }
                }
            });

            BmobQuery<Actor.ActorObj> queryActor=new BmobQuery<>();
            queryActor.findObjects(new FindListener<Actor.ActorObj>() {
                @Override
                public void done(List<Actor.ActorObj> list, BmobException e) {
                    if(e==null){
                        for(Actor.ActorObj obj:list){
                            Actor actor=new Actor();
                            actor.setPicture(ctx.getFilesDir()+"/"+obj.getName()+".jpg");
                            actor.setName(obj.getName());
                            actor.setBundle(ctx.getFilesDir()+"/"+obj.getName()+".assetbundle");
                            new insertActorAsyncTask(asyncActorDao,false).execute(actor);
                            downloadFile(actor.getBundle(),obj.getBundle());
                            downloadFile(actor.getPicture(),obj.getPicture());
                        }
                    }
                }
            });
            return null;
        }
        private void downloadFile(String filename,String url){
            File file=new File(filename);
            if(file.exists())
                return;
            BmobFile bmobfile =new BmobFile(
                    filename
                    ,""
                    ,url
            );
            bmobfile.download(file, new DownloadFileListener() {
                @Override
                public void done(String s, BmobException e) {
                    Log.d("mydebug",s);
                }

                @Override
                public void onProgress(Integer integer, long l) {

                }
            });
        }
    }

}
